package com.tencent.trtc.pk;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.example.basic.TRTCBaseActivity;
import com.tencent.liteav.TXLiteAVCode;
import com.tencent.rtmp.ui.TXCloudVideoView;
import com.tencent.trtc.TRTCCloud;
import com.tencent.trtc.TRTCCloudDef;
import com.tencent.trtc.TRTCCloudListener;
import com.tencent.trtc.debug.GenerateTestUserSig;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * create by xuexuan
 * time 2024/12/30 16:49
 *
 * sdk 的 startPublishMediaStream  和 restapi 的StartPublishCdnStream ，是一样的
 *
 * 在房间A 调用startPublishMediaStream 把房间B用户b1、房间C用户c1，混流后，推到房间机器人mix_robot1 或者 CDN
 *
 * 各房间的机器人状态：
 * 房间A: 如果是推到房间A，则有mix_robot1机器人进房，有收到onRemoteUserEnterRoom回调。
 *       如果是推到 CDN，则有默认机器人进房，没有收到onRemoteUserEnterRoom回调。
 * 房间B: 有mcu 转推机器人进房，没有收到onRemoteUserEnterRoom回调。一个mcu机器人，对应一个转推任务。
 * 房间C: 有mcu 转推机器人进房，没有收到onRemoteUserEnterRoom回调。一个mcu机器人，对应一个转推任务。
 *
 *
 * 在房间A 调用startPublishMediaStream, 把房间A用户a1、房间b用户b1，混流后, 推到房间机器人mix_robot1
 * 因为mix_robot1中包含了a1的流，也就是说房间A中存在两个能看到a1的流，一个是a1自己，一个是mix_robot1，此时的规则是：
 * https://cloud.tencent.com/document/product/647/79634#11c06c485af4d4bd3b60bc0c883a9a32
 * 当您进房前设置的订阅模式均为手动时，您需要自行管理您想要拉取的音视频流（通常当您拉取回推房间的转码流时，您应该取消订阅参与转码的对应音视频单流）。
 * 当您进房前设置的订阅模式均为自动时，不参与转码的用户a2将自动收到后台下发的转码流mix_robot1 并不再继续接收参与转码的音视频单流a1。
 * 除非您明确进行取消订阅，否则转码流数据将持续下发。
 *
 */
public class SubCloudRoomPKActivity extends TRTCBaseActivity {


    private static final String TAG = "ConnectOtherRoom";

    private ImageView mImageBack;
    private TextView mTextTitle;
    private Button mButtonStartPush;
    private Button mButtonStartPK;
    private EditText mEditRoomId;
    private EditText mEditUserId;
    private EditText mEditPKRoomId;
    private TXCloudVideoView mTXCloudPreviewView;
    private TXCloudVideoView mTXCloudRemoteView;

    private int mPKRoomId;
    private TRTCCloud mTRTCCloud;
    private TRTCCloud mSubCloud;

    private String mUserId;
    private boolean mStartPushFlag = false;
    private boolean mStartPKFlag = false;
    private String mTaskIdOfStartPush;
    private List<String> mPKRoomUsers = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sub_cloud_room_pk_activity);
        getSupportActionBar().hide();

        if (checkPermission()) {
            initView();
        }
    }


    @Override
    protected void onPermissionGranted() {
        initView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        exitRoom();
    }


    private void initView() {
        mImageBack = findViewById(R.id.iv_back);
        mTextTitle = findViewById(R.id.tv_room_number);
        mButtonStartPush = findViewById(R.id.btn_start_push);
        mButtonStartPK = findViewById(R.id.btn_start_pk);
        mEditRoomId = findViewById(R.id.et_room_id);
        mEditUserId = findViewById(R.id.et_user_id);
        mEditPKRoomId = findViewById(R.id.et_remote_room_id);
        mTXCloudPreviewView = findViewById(R.id.txcvv_main_local);
        mTXCloudRemoteView = findViewById(R.id.txcvv_video_remote);

        mImageBack.setOnClickListener(mOnClickListener);
        mButtonStartPush.setOnClickListener(mOnClickListener);
        mButtonStartPK.setOnClickListener(mOnClickListener);

        mEditUserId.setText(new Random().nextInt(100000) + 1000000 + "");
        mTextTitle.setText(getString(R.string.connectotherroom_roomid) + ":" + mEditRoomId.getText().toString());
        mPKRoomId = Integer.parseInt(mEditPKRoomId.getText().toString());
    }


    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v.getId() == R.id.iv_back) {
                finish();
            } else if (v.getId() == R.id.btn_start_push) {
                String roomId = mEditRoomId.getText().toString();
                String userId = mEditUserId.getText().toString();
                if (!mStartPushFlag) {
                    if (!TextUtils.isEmpty(roomId) && !TextUtils.isEmpty(userId)) {
                        mButtonStartPush.setText(getString(R.string.connectotherroom_stop_push));
                        enterRoom(roomId, userId);
                        mStartPushFlag = true;
                    } else {
                        Toast.makeText(SubCloudRoomPKActivity.this,
                                        getString(R.string.connectotherroom_please_input_roomid_and_userid), Toast.LENGTH_SHORT)
                                .show();
                    }
                } else {
                    mButtonStartPush.setText(getString(R.string.connectotherroom_start_push));
                    exitRoom();
                    mStartPushFlag = false;
                }


            } else if (v.getId() == R.id.btn_start_pk) {
                if (mStartPKFlag) {
                    mStartPKFlag = false;
                    mTRTCCloud.stopPublishMediaStream(mTaskIdOfStartPush);
                } else {
                    mStartPKFlag = true;
                    startPublishMediaToRoom(mPKRoomUsers);
                }
            }
        }
    };


    private void enterRoom(String roomId, String userId) {
        mUserId = userId;
        mTRTCCloud = TRTCCloud.sharedInstance(getApplicationContext());
        mTRTCCloud.setListener(new SubCloudRoomPKActivity.TRTCCloudImplListener(SubCloudRoomPKActivity.this));
        TRTCCloudDef.TRTCParams mTRTCParams = new TRTCCloudDef.TRTCParams();
        mTRTCParams.sdkAppId = GenerateTestUserSig.SDKAPPID;
        mTRTCParams.userId = userId;
        mTRTCParams.roomId = Integer.parseInt(roomId);
        mTRTCParams.userSig = GenerateTestUserSig.genTestUserSig(mTRTCParams.userId);
        mTRTCParams.role = TRTCCloudDef.TRTCRoleAnchor;

        mTRTCCloud.startLocalPreview(true, mTXCloudPreviewView);
        mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
        mTRTCCloud.enterRoom(mTRTCParams, TRTCCloudDef.TRTC_APP_SCENE_LIVE);
        subCloudEnterRoom();
    }


    private void subCloudEnterRoom() {

        // 创建 TRTC 子实例
        mSubCloud = mTRTCCloud.createSubCloud();
        // 添加子实例事件监听
        mSubCloud.addListener(mSubTRTCCloudImplListener);
        // 子实例进入 PK 房间
        TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();
        params.sdkAppId = GenerateTestUserSig.SDKAPPID;
        params.userId = "Sub_" + mUserId;
        params.userSig = GenerateTestUserSig.genTestUserSig(params.userId);

        params.role = TRTCCloudDef.TRTCRoleAnchor;
        params.roomId = mPKRoomId;
        // 子实例开启本地音频采集和发布
        mSubCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
        // 子实例开启本地视频预览和发布
        mSubCloud.startLocalPreview(true, mTXCloudPreviewView);
        mSubCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_LIVE);

    }


    // 来自 TRTC SDK 的各类事件通知
    private TRTCCloudListener mSubTRTCCloudImplListener = new TRTCCloudListener() {
        @Override
        public void onEnterRoom(long result) {
            if (result > 0) {
                // result 代表加入房间所消耗的时间(毫秒)
                Log.d(TAG, "Enter room succeed!");
                mPKRoomUsers.add("Sub_" + mUserId);

            } else {
                // result 代表进房失败的错误码
                Log.d(TAG, "Enter room failed!");
            }
        }

        @Override
        public void onRemoteUserEnterRoom(String userId) {
            super.onRemoteUserEnterRoom(userId);
            mPKRoomUsers.add(userId);
        }

        @Override
        public void onUserAudioAvailable(String userId, boolean available) {
            // 某远端用户发布/取消了自己的音频
            // 在自动订阅模式下，您无需做任何操作，SDK 会自动播放远端用户音频
        }

        @Override
        public void onUserVideoAvailable(String userId, boolean available) {
            // 某远端用户发布/取消了主路视频画面
            if (available) {
                // 订阅远端用户的视频流，并绑定视频渲染控件
//                mSubCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, remoteView);
            } else {
                // 停止订阅远端用户的视频流，并释放渲染控件
//                mSubCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
            }
        }

        // 开始发布媒体流的事件回调
        @Override
        public void onStartPublishMediaStream(String taskId, int code, String message, Bundle extraInfo) {
            // taskId: 当请求成功时，TRTC 后台会在回调中提供给您这项任务的 taskId，后续您可以通过该 taskId 结合 updatePublishMediaStream 和 stopPublishMediaStream 进行更新和停止
            // code: 回调结果，0 表示成功，其余值表示失败
            if (code == 0) {
                // 主实例停止推流
                mTRTCCloud.stopLocalAudio();
                mTRTCCloud.stopLocalPreview();
                mTaskIdOfStartPush = taskId;

            }
        }
    };


    // 开始发布混合媒体流到 TRTC 房间
    public void startPublishMediaToRoom(List<String> mixUserList) {

        // 媒体流发布的目标地址
        TRTCCloudDef.TRTCPublishTarget target = new TRTCCloudDef.TRTCPublishTarget();
        // 目标地址设定为混流回推到房间
        target.mode = TRTCCloudDef.TRTC_PublishMixStream_ToRoom;
        String roomId = mEditRoomId.getText().toString();
        target.mixStreamIdentity.intRoomId = Integer.parseInt(roomId);
        // 混流机器人用户名不能与房间内其他用户重复
        target.mixStreamIdentity.userId = "mix_robot";

        // 设置媒体流编码输出参数
        TRTCCloudDef.TRTCStreamEncoderParam trtcStreamEncoderParam = new TRTCCloudDef.TRTCStreamEncoderParam();
        trtcStreamEncoderParam.audioEncodedChannelNum = 1;
        trtcStreamEncoderParam.audioEncodedKbps = 50;
        trtcStreamEncoderParam.audioEncodedCodecType = 0;
        trtcStreamEncoderParam.audioEncodedSampleRate = 48000;
        trtcStreamEncoderParam.videoEncodedFPS = 15;
        trtcStreamEncoderParam.videoEncodedGOP = 2;
        trtcStreamEncoderParam.videoEncodedKbps = 1300;
        trtcStreamEncoderParam.videoEncodedWidth = 540;
        trtcStreamEncoderParam.videoEncodedHeight = 960;

        // 媒体流转码配置参数
        TRTCCloudDef.TRTCStreamMixingConfig trtcStreamMixingConfig = new TRTCCloudDef.TRTCStreamMixingConfig();
        if (mixUserList != null) {
            ArrayList<TRTCCloudDef.TRTCUser> audioMixUserList = new ArrayList<>();
            ArrayList<TRTCCloudDef.TRTCVideoLayout> videoLayoutList = new ArrayList<>();

            for (int i = 0; i < mixUserList.size() && i < 16; i++) {
                TRTCCloudDef.TRTCUser user = new TRTCCloudDef.TRTCUser();
                user.intRoomId = mPKRoomId;
                user.userId = mixUserList.get(i);
                audioMixUserList.add(user);

                TRTCCloudDef.TRTCVideoLayout videoLayout = new TRTCCloudDef.TRTCVideoLayout();
                if (mixUserList.get(i).equals("Sub_" + mUserId)) {
                    // 本地主播画面布局
                    videoLayout.x = 0;
                    videoLayout.y = 0;
                    videoLayout.width = 540;
                    videoLayout.height = 960;
                    videoLayout.zOrder = 0;
                } else {
                    // PK 主播画面布局
                    videoLayout.x = 400;
                    videoLayout.y = 5 + i * 245;
                    videoLayout.width = 135;
                    videoLayout.height = 240;
                    videoLayout.zOrder = 1;
                }
                videoLayout.fixedVideoUser = user;
                videoLayout.fixedVideoStreamType = TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG;
                videoLayoutList.add(videoLayout);
            }

            // 指定转码流中的每一路输入音频的信息
            trtcStreamMixingConfig.audioMixUserList = audioMixUserList;
            // 指定混合画面的中每一路视频画面的位置、大小、图层以及流类型等信息
            trtcStreamMixingConfig.videoLayoutList = videoLayoutList;
        }

        // 开始发布媒体流
        // 如果这里使用mTRTCCloud.startPublishMediaStream(target, trtcStreamEncoderParam, trtcStreamMixingConfig); 则在mTRTCCloud房间 还会有一个默认mcu机器人进房
        // 使用mSubCloud.startPublishMediaStream(target, trtcStreamEncoderParam, trtcStreamMixingConfig); 则在mTRTCCloud房间 不会有默认mcu机器人进房
        mSubCloud.startPublishMediaStream(target, trtcStreamEncoderParam, trtcStreamMixingConfig);
    }


    protected class TRTCCloudImplListener extends TRTCCloudListener {

        private WeakReference<SubCloudRoomPKActivity> mContext;

        public TRTCCloudImplListener(SubCloudRoomPKActivity activity) {
            super();
            mContext = new WeakReference<>(activity);
        }

        @Override
        public void onRemoteUserEnterRoom(String s) {
            mTRTCCloud.startRemoteView(s, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, mTXCloudRemoteView);
        }

        @Override
        public void onRemoteUserLeaveRoom(String s, int i) {
            mTRTCCloud.stopRemoteView(s, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
            mStartPKFlag = false;
            mButtonStartPK.setText(R.string.connectotherroom_start_pk);
        }




        @Override
        public void onConnectOtherRoom(String s, int i, String s1) {
            Log.d(TAG, "onConnectOtherRoom: s = " + s + " , i = " + i + " , s1 = " + s1);
        }

        @Override
        public void onDisConnectOtherRoom(int i, String s) {
            Log.d(TAG, "onConnectOtherRoom: s = " + s + " , i = " + i);
        }

        @Override
        public void onError(int errCode, String errMsg, Bundle extraInfo) {
            Log.d(TAG, "sdk callback onError");
            SubCloudRoomPKActivity activity = mContext.get();
            if (activity != null) {
                Toast.makeText(activity, "onError: " + errMsg + "[" + errCode + "]", Toast.LENGTH_SHORT).show();
                if (errCode == TXLiteAVCode.ERR_ROOM_ENTER_FAIL) {
                    activity.exitRoom();
                }
            }
        }

        // 开始发布媒体流的事件回调
        @Override
        public void onStartPublishMediaStream(String taskId, int code, String message, Bundle extraInfo) {
            // taskId: 当请求成功时，TRTC 后台会在回调中提供给您这项任务的 taskId，后续您可以通过该 taskId 结合 updatePublishMediaStream 和 stopPublishMediaStream 进行更新和停止
            // code: 回调结果，0 表示成功，其余值表示失败
            if (code == 0) {

            }
        }
    }


    private void exitRoom() {
        if (mTRTCCloud != null) {
            mTRTCCloud.stopAllRemoteView();
            mTRTCCloud.stopLocalAudio();
            mTRTCCloud.stopLocalPreview();
            mTRTCCloud.exitRoom();
            mTRTCCloud.setListener(null);
        }
        mTRTCCloud = null;
        TRTCCloud.destroySharedInstance();
    }


}
